﻿using PumpAlgorithm;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PLC.Standard
{
    public class CentrifugalPumpPerf
    {
        #region 标准判断

        static Hashtable headLevelTable = null;
        static Hashtable flowLevelTable = null;
        static Hashtable powerLevelTable = null;
        static Hashtable effLevelTable = null;

        static CentrifugalPumpPerf()
        {
              initDic();
         }

        /// <summary>
        /// 初始化流量，扬程，功率，效率标准
        /// </summary>
        public static void initDic()
        {

            flowLevelTable = new Hashtable();
            flowLevelTable.Add("1B", 5);
            flowLevelTable.Add("2B", 8);
            flowLevelTable.Add("3B", 9);

            headLevelTable = new Hashtable();
            headLevelTable.Add("1B", 3);
            headLevelTable.Add("2B", 5);
            headLevelTable.Add("3B", 7);

            powerLevelTable = new Hashtable();
            powerLevelTable.Add("1B", 4);
            powerLevelTable.Add("2B", 8);
            powerLevelTable.Add("3B", 9);

            effLevelTable = new Hashtable();
            effLevelTable.Add("1B", 4);
            effLevelTable.Add("2B", 8);
            effLevelTable.Add("3B", 9);

        }

        /// <summary>
        /// 解方程，用拟合公式求额定扬程下的流量值
        /// </summary>
        /// <param name="paramH"></param>
        /// <param name="head"></param>
        /// <param name="minQ"></param>
        /// <param name="maxQ"></param>
        /// <returns></returns>
        public static Double CaculateResultFlowValue(Double[] paramH, Double head, Double minQ, Double maxQ)
        {
            //Double deltQ = q / 1000.0f;
            Double deltQ = (maxQ - minQ) / 1000.0f;

            Double delaHead = 1000.0f;
            Double currentQ = minQ;

            for (int i = 0; i < 1000; i++)
            {
                Double q = minQ + i * deltQ;
                Double cacuHead = CanonicalAlgorithm.CaculateValue(q, paramH);
                if (Math.Abs(cacuHead - head) < delaHead)
                {
                    delaHead = Math.Abs(cacuHead - head);
                    currentQ = q;
                }
            }

            //求解得到的计算值和额定值的差值小于Epsilon,那么我们认为方程得到有效的解
            if (Math.Abs(delaHead - head / 100.0) > Double.Epsilon)
            {
                return currentQ;
            }


            return Double.NaN;
        }

        /// <summary>
        /// 扬程标准判断
        /// </summary>
        /// <param name="head">计算扬程</param>
        /// <param name="ratedHead">额定扬程</param>
        /// <param name="level">判断等级</param>
        /// <returns></returns>
        public static Boolean JudgeHeadLevel(Double head, Double ratedHead, String level)
        {
            int rate = (int)headLevelTable[level];
            if (((ratedHead * (100 + rate) / 100.0f) - head) > Double.Epsilon && (head - (ratedHead * (100 - rate) / 100.0f) > Double.Epsilon))
            {
                return true;
            }
            return false;

        }

        public static double[] CaculateCrossFlowHead(Double ratedFlow, Double ratedHead, Double maxFlow, Double[] paramH)
        {
            double rate = ratedHead / ratedFlow;

            int seg = 10;
            double startValue = 0;
            double endValue = maxFlow;

            //最大的额定流量算出的扬程还大于额定流量的话，说明不会找到焦点
            if (CanonicalAlgorithm.CaculateValue(maxFlow, paramH) - ratedHead > Double.Epsilon)
            {
                return null;
            }
            int caculateCount = 0;
            do
            {

                for (int i = 0; i < seg; i++)
                {
                    double segValue = startValue + ((endValue - startValue) / seg) * i;

                    double curveHead = CanonicalAlgorithm.CaculateValue(segValue, paramH);
                    double segValueEnd = startValue + ((endValue - startValue) / seg) * (i + 1);
                    double curveHeadEnd = CanonicalAlgorithm.CaculateValue(segValueEnd, paramH);
                    //double deltaMax = caculateValue(segMax, paramH)-rate* segMax;
                    if (Math.Abs(curveHead - ratedHead) < 0.00001)
                    {
                        double[] ret = new double[] { segValue, curveHead };
                        return ret;
                    }

                    if ((curveHead - ratedHead > Double.Epsilon) && (ratedHead - curveHeadEnd > Double.Epsilon))
                    {
                        startValue = segValue;
                        endValue = segValueEnd;
                        break;
                    }
                }
                caculateCount++;

            } while (caculateCount <= 10);
            return null;

        }


        /*
        static Hashtable headLevelTable = null;
        static Hashtable flowLevelTable = null;
        static Hashtable powerLevelTable = null;
        static Hashtable effLevelTable = null;

        static CentrifugalPumpPerf()
        {
              initDic();
        }

        /// <summary>
        /// 初始化流量，扬程，功率，效率标准
        /// </summary>
        public static void initDic()
        {

            flowLevelTable = new Hashtable();
            flowLevelTable.Add("1B", 5);
            flowLevelTable.Add("2B", 8);
            flowLevelTable.Add("3B", 9);

            headLevelTable = new Hashtable();
            headLevelTable.Add("1B", 3);
            headLevelTable.Add("2B", 5);
            headLevelTable.Add("3B", 7);

            powerLevelTable = new Hashtable();
            powerLevelTable.Add("1B", 4);
            powerLevelTable.Add("2B", 8);
            powerLevelTable.Add("3B", 9);

            effLevelTable = new Hashtable();
            effLevelTable.Add("1B", 4);
            effLevelTable.Add("2B", 8);
            effLevelTable.Add("3B", 9);

        }


        /// <summary>
        /// 扬程标准判断
        /// </summary>
        /// <param name="head">计算扬程</param>
        /// <param name="ratedHead">额定扬程</param>
        /// <param name="level">判断等级</param>
        /// <returns></returns>
        public static Boolean JudgeHeadLevel(Double head, Double ratedHead,  level)
        {
            int rate = (int)headLevelTable[level];
            if (((ratedHead * (100 + rate) / 100.0f) - head) > Double.Epsilon && (head - (ratedHead * (100 - rate) / 100.0f) > Double.Epsilon))
            {
                return true;
            }
            return false;

        }

       
        /// <summary>
        /// 流量标准判断
        /// </summary>
        /// <param name="flow">计算流量</param>
        /// <param name="ratedFlow">额定流量</param>
        /// <param name="level">判断等级</param>
        /// <returns></returns>
        public static Boolean JudgeFlowLevel(Double flow, Double ratedFlow, FlowHeadLevel level)
        {
            int rate = (int)flowLevelTable[level];
            if (((ratedFlow * (100 + rate) / 100.0f) - flow) > Double.Epsilon && (flow - (ratedFlow * (100 - rate) / 100.0f) > Double.Epsilon))
            {
                return true;
            }
            return false;
        }

        /// <summary>
        /// 功率标准判断
        /// </summary>
        /// <param name="power">功率</param>
        /// <param name="ratedPower">额定功率</param>
        /// <param name="level">等级</param>
        /// <returns></returns>

        public static Boolean JudgePowerLevel(Double power, Double ratedPower, String level)
        {
            int rate = (int)powerLevelTable[level];
            if (((ratedPower * (100 + rate) / 100.0f) - power) > Double.Epsilon)
            {
                return true;
            }
            return false;
        }

        /// <summary>
        /// 效率判断等级
        /// </summary>
        /// <param name="eff">效率</param>
        /// <param name="ratedEff">额定效率</param>
        /// <param name="level">等级</param>
        /// <returns></returns>
        public static Boolean JudgeEffLevel(Double eff, Double ratedEff, String level)
        {
            int rate = (int)effLevelTable[level];
            if ((eff - ratedEff * (100 - rate) / 100.0f) > Double.Epsilon)
            {
                return true;
            }
            return false;
        }


        /// <summary>
        /// 根据标准设置流量，养成的范围
        /// </summary>
        /// <param name="flow"></param>
        /// <param name="head"></param>
        /// <param name="level"></param>
        /// <returns></returns>
        public static Double[,] GetFlowHeadRange(Double flow, Double head, String level)
        {
            int flowRate = (int)flowLevelTable[level];
            int headHead = (int)headLevelTable[level];


            double startFlow = flow * (1.0f - flowRate / 100.0f);
            double endFlow = flow * (1.0f + flowRate / 100.0f);

            double startHead = head * (1.0f - headHead / 100.0f);
            double endHead = head * (1.0f + headHead / 100.0f);

            Double[,] ret = new Double[4, 2]
            {
                { startFlow, head },
                { endFlow,   head },
                { flow,      startHead},
                { flow,      endHead}
            };
            return ret;
        }

        public static Double[,] GetFlowPowerRange(Double flow, Double power, String level)
        {
            int flowRate = (int)flowLevelTable[level];
            int powerRate = (int)powerLevelTable[level];


            double startFlow = flow * (1.0f - flowRate / 100.0f);
            double endFlow = flow * (1.0f + flowRate / 100.0f);

            double startPower = power;
            double endPower = power * (1.0f + powerRate / 100.0f);

            Double[,] ret = new Double[4, 2]
            {
                { startFlow, power },
                { endFlow,   power },
                { flow,      startPower},
                { flow,      endPower}
            };
            return ret;
        }

        public static Double[,] GetFlowEffRange(Double flow, Double eff, String level)
        {
            int flowRate = (int)flowLevelTable[level];
            int effRate = (int)effLevelTable[level];

            double startFlow = flow * (1.0f - flowRate / 100.0f);
            double endFlow = flow * (1.0f + flowRate / 100.0f);

            double startEff = eff * (1.0f - effRate / 100.0f);
            double endEff = eff;

            Double[,] ret = new Double[4, 2]
            {
                { startFlow, eff },
                { endFlow,   eff },
                { flow,      startEff},
                { flow,      endEff}
            };
            return ret;
        }
        */
        #endregion
    }
}
